use serde::{Deserialize, Serialize};
use std::fs::{File, OpenOptions};
use std::io::{BufRead, BufReader, Write};
use std::path::PathBuf;
use chrono::{Local};
use tauri::Manager;
use log::{info, warn, error};

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct LogEntry {
    pub timestamp: String,
    pub level: String,
    pub module: String,
    pub message: String,
    pub details: Option<String>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct LogFilter {
    pub level: Option<String>,
    pub module: Option<String>,
    pub start_time: Option<String>,
    pub end_time: Option<String>,
    pub keyword: Option<String>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct LogResponse {
    pub logs: Vec<LogEntry>,
    pub total: usize,
    pub page: usize,
    pub page_size: usize,
}

// 获取日志文件路径
fn get_log_file_path(app_handle: &tauri::AppHandle) -> Result<PathBuf, String> {
    let app_dir = app_handle
        .path()
        .app_data_dir()
        .map_err(|e| format!("无法获取应用目录: {}", e))?;

    std::fs::create_dir_all(&app_dir)
        .map_err(|e| format!("创建应用目录失败: {}", e))?;

    Ok(app_dir.join("app.log"))
}

// 写入日志到文件
pub fn write_log_to_file(app_handle: &tauri::AppHandle, entry: &LogEntry) -> Result<(), String> {
    let log_file_path = get_log_file_path(app_handle)?;

    let mut file = OpenOptions::new()
        .create(true)
        .append(true)
        .open(&log_file_path)
        .map_err(|e| format!("打开日志文件失败: {}", e))?;

    let log_line = format!(
        "[{}] [{}] [{}] {} {}\n",
        entry.timestamp,
        entry.level,
        entry.module,
        entry.message,
        entry.details.as_deref().unwrap_or("")
    );

    file.write_all(log_line.as_bytes())
        .map_err(|e| format!("写入日志失败: {}", e))?;

    Ok(())
}

// 记录系统日志
#[tauri::command]
pub async fn log_system_event(
    level: String,
    module: String,
    message: String,
    details: Option<String>,
    app_handle: tauri::AppHandle,
) -> Result<(), String> {
    let entry = LogEntry {
        timestamp: Local::now().format("%Y-%m-%d %H:%M:%S%.3f").to_string(),
        level: level.clone(),
        module: module.clone(),
        message: message.clone(),
        details: details.clone(),
    };

    // 写入文件
    write_log_to_file(&app_handle, &entry)?;

    // 同时输出到控制台
    match level.to_uppercase().as_str() {
        "ERROR" => error!("[{}] {}: {}", module, message, details.unwrap_or_default()),
        "WARN" => warn!("[{}] {}: {}", module, message, details.unwrap_or_default()),
        _ => info!("[{}] {}: {}", module, message, details.unwrap_or_default()),
    }

    Ok(())
}

// 获取日志列表
#[tauri::command]
pub async fn get_logs(
    filter: LogFilter,
    page: usize,
    page_size: usize,
    app_handle: tauri::AppHandle,
) -> Result<LogResponse, String> {
    let log_file_path = get_log_file_path(&app_handle)?;

    if !log_file_path.exists() {
        return Ok(LogResponse {
            logs: vec![],
            total: 0,
            page,
            page_size,
        });
    }

    let file = File::open(&log_file_path)
        .map_err(|e| format!("打开日志文件失败: {}", e))?;

    let reader = BufReader::new(file);
    let mut logs = Vec::new();

    for line in reader.lines() {
        let line = line.map_err(|e| format!("读取日志行失败: {}", e))?;
        if let Some(entry) = parse_log_line(&line) {
            if matches_filter(&entry, &filter) {
                logs.push(entry);
            }
        }
    }

    // 按时间倒序排列（最新的在前）
    logs.reverse();

    let total = logs.len();
    let start = page * page_size;
    let end = std::cmp::min(start + page_size, total);

    let page_logs = if start < total {
        logs[start..end].to_vec()
    } else {
        vec![]
    };

    Ok(LogResponse {
        logs: page_logs,
        total,
        page,
        page_size,
    })
}

// 清空日志
#[tauri::command]
pub async fn clear_logs(app_handle: tauri::AppHandle) -> Result<(), String> {
    let log_file_path = get_log_file_path(&app_handle)?;

    if log_file_path.exists() {
        std::fs::remove_file(&log_file_path)
            .map_err(|e| format!("删除日志文件失败: {}", e))?;
    }

    info!("日志文件已清空");
    Ok(())
}

// 导出日志
#[tauri::command]
pub async fn export_logs(
    export_path: String,
    app_handle: tauri::AppHandle,
) -> Result<(), String> {
    let log_file_path = get_log_file_path(&app_handle)?;

    if !log_file_path.exists() {
        return Err("日志文件不存在".to_string());
    }

    std::fs::copy(&log_file_path, &export_path)
        .map_err(|e| format!("导出日志失败: {}", e))?;

    info!("日志已导出到: {}", export_path);
    Ok(())
}

// 解析日志行
fn parse_log_line(line: &str) -> Option<LogEntry> {
    // 解析格式: [timestamp] [level] [module] message details
    let parts: Vec<&str> = line.splitn(4, ']').collect();
    if parts.len() < 4 {
        return None;
    }

    let timestamp = parts[0].trim_start_matches('[').to_string();
    let level = parts[1].trim_start_matches(' ').trim_start_matches('[').to_string();
    let module = parts[2].trim_start_matches(' ').trim_start_matches('[').to_string();
    let rest = parts[3].trim_start_matches(' ');

    let (message, details) = if let Some(pos) = rest.find(' ') {
        let msg = rest[..pos].to_string();
        let det = rest[pos + 1..].to_string();
        (msg, if det.is_empty() { None } else { Some(det) })
    } else {
        (rest.to_string(), None)
    };

    Some(LogEntry {
        timestamp,
        level,
        module,
        message,
        details,
    })
}

// 检查日志条目是否匹配过滤条件
fn matches_filter(entry: &LogEntry, filter: &LogFilter) -> bool {
    if let Some(ref level) = filter.level {
        if entry.level != *level {
            return false;
        }
    }

    if let Some(ref module) = filter.module {
        if !entry.module.contains(module) {
            return false;
        }
    }

    if let Some(ref keyword) = filter.keyword {
        if !entry.message.contains(keyword) &&
            !entry.details.as_ref().unwrap_or(&String::new()).contains(keyword) {
            return false;
        }
    }

    // TODO: 实现时间范围过滤

    true
}